<?php
/**
 * コアユーティリティクラス
 * 
 * 1.0 2010.11.19 初期リリース
 * 
 * @filesource CoreUtility.class.php
 * @package forty-two
 * @subpackage forty-two
 * @version 1.0
 */

// PHP標準定数「DIRECTORY_SEPARATOR」のエイリアス定数DS未定義時
if (!defined('DS')) {
    define('DS', DIRECTORY_SEPARATOR);
}


/**
 * コアユーティリティクラス
 * 
 * 1.0 2010.11.19 初期リリース
 * 
 * @author koto
 * @package forty-two
 * @version 1.0
 */
class CoreUtility
{
    /**
     * 実行時間取得処理
     * 
     * @since 1.0
     * @access static
     * @param string  $name    計測名指定(未指定：EXECUTION_START_TIME)
     * @param float(実行経過時間)
     */
    static function getExecTime($name = 'EXECUTION_START_TIME')
    {
       global $___execStartTime;
       if ($name == 'EXECUTION_START_TIME' && defined('EXECUTION_START_TIME'))
       {
           $___execStartTime[$name] = EXECUTION_START_TIME;
       }
       else if (!isset($___execStartTime[$name]))
       {
           return FALSE;
       }
       list($usec, $sec) = explode(" ", microtime());
       return ((float)$usec + (float)$sec) - $___execStartTime[$name];
    }
    
    
    
    /**
     * 実行時間設定処理
     * 
     * @since 1.0
     * @access static
     * @param string  $name    計測名指定(未指定：'')
     * @param float(開始時間) | boolean
     */
    static function setExecTime($name = '')
    {
       global $___execStartTime;
       if (isset($name) && strlen($name) > 0)
       {
           list($usec, $sec) = explode(" ", microtime());
           $___execStartTime[$name] = ((float)$usec + (float)$sec);
           return $___execStartTime[$name];
       }
       return FALSE;
    }
    
    
    
    /**
     * var_dump結果文字列取得処理
     * 
     * @since 1.0
     * @access static
     * @param mixi  $vars    変数
     * @param string
     */
    static function cdump($vars = NULL)
    {
        // 値の取得
        ob_start();
        var_dump($vars);
        $buf =& ob_get_contents();
        ob_end_clean();
       return $buf;
    }
    
    
    
    /**
     * リダイレクト処理
     * 
     * @since 1.0
     * @access static
     * @param string  $url    リダイレクト先URL
     * @param void
     */
    static function redirect($url = '')
    {
        if (isset($url) && strlen($url) > 0)
        {
            header('Location: ' . $url);
            exit;
        }
        return;
    }
    
    
    
    /**
     * 定数取得処理
     * 
     * @since 1.0
     * @access static
     * @param string  $name    定数名
     * @param void
     */
    static function getDefineData($name='') {
        if (strlen($name) && defined(strtoupper($name)))
        {
           return unserialize(constant(strtoupper($name)));
        }
        else
        {
            return NULL;
        }
    }
    
    
    
    /**
     * html_special_chars処理を元に戻す処理
     * 
     * @since 1.0
     * @access static
     * @param string  $str    対象文字列
     * @return void
     */
    static function unHtmlSpecialChars($str)
    {
        $trans_tbl = get_html_translation_table(HTML_ENTITIES);
        $trans_tbl = array_flip($trans_tbl);
        return strtr($str, $trans_tbl);
    }
    
    
    
    /**
     * 一定文字数改行処理(多次元配列対応版)
     * 
     * 再起処理をしているので、あまりデータが多いと処理に時間が掛かりすぎます。
     * 
     * @since 1.0
     * @access static
     * @param array   $data       対象文字列
     * @param array   $exception  改行除外配列
     * @param string  $limit      改行文字数
     * @param string  $code       文字コード
     * @return void
     */
    static function strCutArray($data = array(), $exception = array(),$limit = 50, $code = CHARA_SET_INNER)
    {
        if (is_array($data))
        {
            foreach ($data as $k => $v) 
            {
                if (!in_array($k, $exception))
                {
                    if (is_array($v))
                    {
                        $v = CoreUtility::strCutArray($v, $exception, $limit, $code);
                    }
                    else if (is_string($v))
                    {
                        $v = CoreUtility::strCut($v, $limit, $code);
                    }
                }
                $returnDate[$k] = $v;
            }
        }
        else if(is_string($data))
        {
            $returnDate = CoreUtility::strCut($data, $limit, $code);
        }
        else
        {
            return FALSE;
        }
        return isset($returnDate)?$returnDate:FALSE;
    }
    
    
    
    /**
     * 一定文字数改行処理
     * 
     * @since 1.0
     * @access static
     * @param string  $data    対象文字列
     * @param string  $limit   改行文字数
     * @param string  $code    文字コード
     * @return void
     */
    static function strCut($data ='', $limit = 50, $code = CHARA_SET_INNER)
    {
        // HTML_SPECIALCHARS処理の掛かったものを元に戻す置換
        $data = CoreUtility::unHtmlSpecialChars($data);
        
        $temp = $data;
        // convert any Line-Terminater to 'LF'("\n")
        $temp = str_replace("\r\n","\n",$temp);
        $temp = str_replace("\r","\n",$temp);
        $t_body = strip_tags($temp);
        $t_body = split("\n",$temp);
        $t = "";
        
        // insert "\n"
        foreach ($t_body as $key => $value)
        {
            if (mb_strlen($value, $code)>$limit)
            {
                for ($i=0;$i<(mb_strlen($value,$code)/$limit);$i++)
                {
                    $t .= mb_substr($value,$i*$limit,$limit,$code)."\n";
                }
                $t_body[$key] = $t; 
            }
        }
        $data = implode("\n",$t_body);
        $data = htmlspecialchars($data);
        $data = nl2br($data);
        return $data;
    }
    
    
    
    /**
     * 配列変数文字コード変換処理(多次元配列対応版)
     * 
     * 再起処理をしているので、あまりデータが多いと処理に時間が掛かりすぎます。
     * 
     * @since 1.0
     * @access static
     * @param array   $data           対象文字列
     * @param array   $exception      改行除外配列
     * @param string  $charaSetOutput 変換後文字コード
     * @param string  $charaSetInner  変換元文字コード
     * @return void
     */
    static function mb_convert_encoding_Array(
        $data = array(), $exception = array(),
        $charaSetOutput = CHARA_SET_OUTPUT, $charaSetInner = CHARA_SET_INNER
    ) {
        if (is_array($data))
        {
            foreach ($data as $k => $v) 
            {
                if (!in_array($k, $exception))
                {
                    if (is_array($v))
                    {
                        $v = CoreUtility::mb_convert_encoding_Array($v, $exception, $charaSetOutput, $charaSetInner);
                    }
                    else if (is_string($v))
                    {
                        $v = mb_convert_encoding($v, $charaSetOutput, $charaSetInner);
                    }
                }
                $returnDate[$k] = $v;
            }
        }
        else if(is_string($data))
        {
            $returnDate = mb_convert_encoding($data, $charaSetOutput, $charaSetInner);
        }
        else
        {
            return FALSE;
        }
        return isset($returnDate)?$returnDate:FALSE;
    }
    
    
    
    /**
     * HTMLテーブル整形メソッド
     *
     * @since 1.0
     * @static
     * @access private
     * @param array $tableArr テーブル生成用データ配列
     * 
     * // 引数フォーマット
     * $tableArr = array(
     *       array(
     *           array('data' => 'test text1-1', 'type' => 'td', 'setting' => '')
     *          ,array('data' => 'test text1-2', 'type' => 'td', 'setting' => '')
     *          ,'option' => array('type' => 'tr', 'setting' => '')
     *       )
     *      ,array(
     *           array('data' => 'test text2-1', 'type' => 'td', 'setting' => '')
     *          ,array('data' => 'test text2-2', 'type' => 'td', 'setting' => '')
     *          ,'option' => array('type' => 'tr', 'setting' => '')
     *       )
     *      ,'option' => array('type' => 'table', 'setting' => 'border="1"')
     * );
     * 
     * 
     * @return boolean FALSE 実行失敗
     * @return string $htmlTable 生成HTMLテーブルソース
     */
    static function factoryHtmlTable ($tableArr = array())
    {
        // 引数確認：配列かどうか
        if (!is_array($tableArr) || count($tableArr) <= 0) {
            return FALSE;
        }
        
        // 戻り値保持用変数初期化
        $htmlTable = '';
        
        // <tr></tr>格納用変数初期化
        $htmlTr = '';
        // ■<table></table>生成処理
        foreach ($tableArr as $keyTable => $trArr)
        {
            // 確認：配列かどうか
            if (!is_array($trArr) || count($trArr) <= 0) {
                return FALSE;
            }
            // tableオプション時は処理しない
            if ($keyTable === 'option') {
                continue;
            }
            
            // <td></td>格納用変数初期化
            $htmlTd = '';
            foreach ($trArr as $keyTr => $tdArr)
            {
                // 確認：配列かどうか
                if (!is_array($tdArr) || count($tdArr) <= 0) {
                    return FALSE;
                }
                // trオプション時は処理しない
                if ($keyTr === 'option') {
                    continue;
                }
                
                // 確認：TD設定
                $tdArr['type'] = (isset($tdArr['type'])&&(strlen($tdArr['type'])>0)) ? $tdArr['type'] : 'td';
                $tdArr['setting'] = (isset($tdArr['setting'])&&(strlen($tdArr['setting'])>0)) ? ' '.$tdArr['setting'] : '';
                // HTML生成：列区分<td>の取り付け
                $htmlTd .= sprintf('    <%s%s>%s</%s>'.BR, $tdArr['type'], $tdArr['setting'], $tdArr['data'] ,$tdArr['type']);
            }
            
            
            // 確認：TR設定
            $typeTr = (isset($trArr['option']['type'])&&(strlen($trArr['option']['type'])>0)) ? $trArr['option']['type'] : 'tr';
            $settingTr = (isset($trArr['option']['setting'])&&(strlen($trArr['option']['setting'])>0)) ? ' '.$trArr['option']['setting'] : '';
            // HTML生成：行区分<tr>の取り付け
            $htmlTr .= sprintf('  <%s%s>'.BR.'%s  </%s>'.BR, $typeTr, $settingTr, $htmlTd ,$typeTr);
        }
        
        // 確認：TABLE設定
        $typeTable = (isset($tableArr['option']['type'])&&(strlen($tableArr['option']['type'])>0)) ? $tableArr['option']['type'] : 'table';
        $settingTable = (isset($tableArr['option']['setting'])&&(strlen($tableArr['option']['setting'])>0)) ? ' '.$tableArr['option']['setting'] : '';
        // HTML生成：表区分<table>の取り付け
        $htmlTable = sprintf('<%s%s>'.BR.'%s</%s>'.BR, $typeTable, $settingTable, $htmlTr, $typeTable);
        
        // 戻り値：生成HTMLテーブルソース
        return $htmlTable;
    }
    
    
    
    /**
     * アクセスIPが含まれるかチェック処理
     * 
     * チェック対象のIPアドレスにアクセスIPが含まれるかチェックする。
     * 
     * @since 1.0
     * @access static
     * @param void
     * @return boolean
     */
    static function checkAccessIPAddress($checkIPAddress = array())
    {
        // アクセスIPアドレス
        $REMOTE_ADDR = $_SERVER['REMOTE_ADDR'];
        
        // 一致するIPがあるか確認
        if (isset($checkIPAddress) && is_array($checkIPAddress) && count($checkIPAddress)>0) {
            foreach ($checkIPAddress as $k => $v) {
                if ($v == $REMOTE_ADDR || CU::inCIDR($REMOTE_ADDR, $v)) {
                    return TRUE;
                }
            }
        } else if (isset($checkIPAddress)
         && is_string($checkIPAddress)
         && (($checkIPAddress == $REMOTE_ADDR) || CU::inCIDR($REMOTE_ADDR, $checkIPAddress))
        ) {
            return FALSE;
        }
        return FALSE;
    }
    
    
    
    /**
     * 指定IPが指定IPアドレス帯に含まれるかチェック処理
     * 
     * 指定IPが指定IPアドレス帯が含まれるかチェックする。
     * 
     * @since 1.0
     * @access static
     * @param void
     * @return boolean
     */
    static function inCIDR($ip, $cidr)
    {
        if (!is_array(stripos($cidr, '/'))) {
            return FALSE;
        }
        list($network, $mask_bit_len) = explode('/', $cidr);
        $host = 32 - $mask_bit_len;
        $net = ip2long($network) >> $host << $host; // 11000000101010000000000000000000
        $ip_net = ip2long($ip) >> $host << $host; // 11000000101010000000000000000000
        return $net === $ip_net;
    }
    
    
    
    /**
     * 指定パスの存在確認＆作成処理
     * 
     * 指定パスが存在するかチェックし、なければ作成する。
     * 
     * @since 1.0
     * @access static
     * @param void
     * @return boolean
     */
    static function cmkdir($path = NULL, $base = NULL)
    {
        // 確認
        if (!is_null($base)&&(!is_dir($base))) {
            return FALSE;
        }
        
        // 引数チェック
        if (!is_string($path)||strlen($path)<=0) {
            return FALSE;
        }
        
        // ファイル、ディレクトリが存在するか確認
        if (is_file($path)||is_dir($path)) {
            return TRUE;
        }
        
        // パスを配列化
        $dirArr = split(DS, $path);
        if (!is_array($dirArr)||count($dirArr)<=0) {
            return FALSE;
        }
        
        // ディレクトリ生成
        $dir = DS;
        $flag = FALSE;
        foreach ($dirArr as $k => $v)
        {
            if ((!is_null($base)&&$base==$dir)||$flag||is_null($base)) {
                $flag = TRUE;
            }
            if (!is_dir($dir)&&$flag) {
                mkdir($dir);
            }
            $dir .= $v.DS;
        }
        
        return is_dir($path);
    }
}


/**
 * コアユーティリティ ショートコール クラス
 */
class CU extends CoreUtility
{
}
?>